package com.chen.auth.service.impl;

import cn.hutool.core.util.StrUtil;
import com.chen.auth.entity.OauthClientDetails;
import com.chen.auth.event.LogoutSuccessEvent;
import com.chen.auth.mapper.OauthClientDetailsMapper;
import com.chen.auth.service.TokenService;
import com.chen.base.utils.SpringContextHolder;
import com.chen.root.base.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @author: ~龙~
 * @date: 2023/6/19 9:50
 **/
@Slf4j
@Service
public class TokenServiceImpl implements TokenService {

    @Value("${server.port}")
    String port;
    @Resource
    TokenStore tokenStore;
    @Resource
    RestTemplate restTemplate;
    @Resource
    OauthClientDetailsMapper oauthClientDetailsMapper;

    @Override
    public R logout(String token) {
        if (StrUtil.isBlank(token)) {
            return R.ok(Boolean.FALSE, "退出失败，token 为空");
        }

        String tokenValue = token.replace(OAuth2AccessToken.BEARER_TYPE, "").trim();

        OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
        if (accessToken == null || StrUtil.isBlank(accessToken.getValue())) {
            return R.ok(Boolean.TRUE, "退出失败，token 无效");
        }
        OAuth2Authentication auth2Authentication = tokenStore.readAuthentication(accessToken);
        // 清空用户信息
        // 清空access token
        tokenStore.removeAccessToken(accessToken);
        // 清空 refresh token
        OAuth2RefreshToken refreshToken = accessToken.getRefreshToken();
        if (refreshToken != null){
            tokenStore.removeRefreshToken(refreshToken);
        }
        // 发送退出成功事件
        SpringContextHolder.publishEvent(new LogoutSuccessEvent(auth2Authentication));
        return R.ok(null,"退出成功");
    }

    @Override
    public R login(Map<String,Object> map) {
        MultiValueMap<String,Object> paramsMap = new LinkedMultiValueMap<>();
        map.keySet().forEach(key -> paramsMap.set(key,map.get(key)));

        // 检查并配置客户端信息
        Object clientIdObj = map.get("client_id");
        Object clientSecretObj = map.get("client_secret");
        String clientId;
        String clientSecret;

        if (clientIdObj != null && clientSecretObj != null){
            clientId = clientIdObj.toString();
            clientSecret = clientSecretObj.toString();
        }else {
            OauthClientDetails clientDetails = oauthClientDetailsMapper.selectById("app-client");
            clientId = clientDetails.getClientId();
            clientSecret = clientDetails.getClientSecretPlaintext();

            paramsMap.set("client_id",clientId);
            paramsMap.set("client_secret",clientSecret);
            paramsMap.set("scope",clientDetails.getScope());
        }

        restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(clientId,clientSecret));
        String url = String.format("http://localhost:%s/oauth/token",port);
        Map tokenMap = restTemplate.postForObject(url, paramsMap, Map.class);
        if (tokenMap.get("access_token") != null){
            return R.ok(tokenMap,"登录成功！");
        }

        return R.failed(null, String.valueOf(tokenMap.get("error_description")));
    }
}
